package com.mall.common.util;

import static com.mall.common.bean.CommonAttributes.CACHE_DICTIONARY_KEY_PREFIX;
import static com.mall.common.bean.CommonAttributes.CACHE_NAME;
import static com.mall.common.bean.CommonAttributes.CONFIG_FILE_NAME;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;

import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;

import com.mall.common.CommonSetting;
import com.mall.common.bean.CommonAttributes;

public class CommonSettingUtils {

	protected static final BeanUtilsBean beanUtilsBean;
	protected static final JsonConfig jsonConfig = new JsonConfig();
	private static JdbcTemplate jdbcTemplate = (JdbcTemplate) SpringUtils.getBean("jdbcTemplate");
	
	static{
		MyConvertUtils myConvertUtils = new MyConvertUtils();
		DateConverter dateconverter = new DateConverter();
		dateconverter.setPatterns(CommonAttributes.DATE_PATTERNS);
		myConvertUtils.register(dateconverter, Date.class);
		beanUtilsBean = new BeanUtilsBean(myConvertUtils);
		jsonConfig.registerJsonValueProcessor("config", new JsonValueProcessor() {
			
			@Override
			public Object processObjectValue(String arg0, Object arg1, JsonConfig arg2) {
				if(arg1 != null){
					return JSONObject.fromObject(arg1);
				}
				return null;
			}
			
			@Override
			public Object processArrayValue(Object arg0, JsonConfig arg1) {
				return null;
			}
		});
	}
	
	public static CommonSetting get(){
		return get(CommonSetting.class);
	}
	
    /**
     * 获取系统配置信息
     * @return
     */
	@SuppressWarnings("unchecked")
	public static <T> T get(Class<T> clazz) {
		String className = clazz.getName();
		Object obj = CacheUtils.getCacheValue(CACHE_NAME, clazz.getName());
		T setting = null;
		if (obj != null) {
			setting = (T) obj;
		} else {
			try {
				setting = clazz.newInstance();
				File file = new ClassPathResource(CONFIG_FILE_NAME).getFile();
				Document document = (new SAXReader()).read(file);

				List<org.dom4j.Element> list = document.selectNodes("/system/common");
				if(!className.contains("CommonSetting")){
					list.addAll(document.selectNodes("/system/setting"));
				}
				for (Iterator<org.dom4j.Element> iterator = list.iterator(); iterator.hasNext();){
					org.dom4j.Element element1 = iterator.next();
					String s = element1.attributeValue("name");
					String s1 = element1.attributeValue("value");
					try {
						beanUtilsBean.setProperty(setting, s, s1);
					} catch (IllegalAccessException illegalaccessexception) {
						illegalaccessexception.printStackTrace();
					}
					catch (InvocationTargetException invocationtargetexception) {
						invocationtargetexception.printStackTrace();
					}
				}
			} catch (Exception exception) {
				exception.printStackTrace();
			}
			CacheUtils.setCacheValue(CACHE_NAME, clazz.getName(), setting);
		}
		return setting;
    }

	/**
	 *@param setting
	 * @param modifyWithSettingNode setting参数类型class为Setting时true,否则false
	 */
	@SuppressWarnings("unchecked")
	public static void set(CommonSetting setting, Boolean modifyWithSettingNode) {
		File file = null;
		Document document = null;
		FileOutputStream fileoutputstream = null;
		XMLWriter xmlwriter = null;
		try{
			file = new ClassPathResource(CONFIG_FILE_NAME).getFile();
			document = (new SAXReader()).read(file);
		}catch (Exception e) {
			e.printStackTrace();
		}
		List<org.dom4j.Element> list = document.selectNodes("/system/common");
		if(modifyWithSettingNode){
			list.addAll(document.selectNodes("/system/setting"));
		}
		for (Iterator<org.dom4j.Element> iterator = list.iterator(); iterator.hasNext();) {
			org.dom4j.Element element = iterator.next();
			try {
				String s = element.attributeValue("name");
				String s1 = beanUtilsBean.getProperty(setting, s);
				Attribute attribute = element.attribute("value");
				attribute.setValue(s1);
			} catch (IllegalAccessException illegalaccessexception) {
				illegalaccessexception.printStackTrace();
			} catch (InvocationTargetException invocationtargetexception) {
				invocationtargetexception.printStackTrace();
			} catch (NoSuchMethodException nosuchmethodexception) {
				nosuchmethodexception.printStackTrace();
			}
		}
		
		try {
			OutputFormat outputformat = OutputFormat.createPrettyPrint();
			outputformat.setEncoding("UTF-8");
			outputformat.setIndent(true);
			outputformat.setIndent("\t");
			outputformat.setNewlines(true);
			fileoutputstream = new FileOutputStream(file);
			xmlwriter = new XMLWriter(fileoutputstream, outputformat);
			xmlwriter.write(document);
		} catch (Exception exception1) {
			exception1.printStackTrace();
		} finally {
			if (xmlwriter != null){
				try {
					xmlwriter.close();
				} catch (IOException ioexception) { 
					
				}
			}
			if(fileoutputstream != null){
				try {
					fileoutputstream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		CacheUtils.clearCache(CACHE_NAME);
	}
    
    /**
     * 获取数据字典
     * @param key
     * @return
     */
    public static JSONObject getDictionaryDataForJSON(String key){
    	if(StringUtils.isBlank(key)){
    		return null;
    	}
    	String code = CACHE_DICTIONARY_KEY_PREFIX + key;
    	Object obj = CacheUtils.getCacheValue(CACHE_NAME, code);
    	if(obj == null){
    		List<Map<String, Object>> dictionaries = jdbcTemplate.queryForList("select * from s_dictionary where decode=? order by decode", new Object[]{key});
    		if(dictionaries == null || dictionaries.isEmpty()){
    			return null;
    		}
    		Map<String, Object> dictionary = dictionaries.get(0);
    		JSONObject jObj = JSONObject.fromObject(dictionary);
    		CacheUtils.setCacheValue(CACHE_NAME, code, jObj);
    		return jObj;
    	}
    	return (JSONObject) obj;
    }
    
    /**
     * 获取数据字典配置
     * @param key 
     * @return
     */
    public static JSONObject getDictionaryConfig(String key){
    	JSONObject jObj = getDictionaryDataForJSON(key);
    	if(jObj == null){
    		return null;
    	}
    	Object obj = jObj.get("config");
    	if(obj != null){
    		return JSONObject.fromObject(obj);
    	}
    	return null;
    }
    
    /**
     * 获取直接下级字典列表
     * @param parentCode
     * @return
     */
	public static JSONArray getDictionaryDataListForJSON(String parentCode){
    	JSONObject jObj = getDictionaryDataForJSON(parentCode);
    	if(jObj == null){
    		return null;
    	}
    	Object obj = jObj.get("sub");
    	if(obj == null){
    		List<Map<String, Object>> dictionaries = jdbcTemplate.queryForList("select * from s_dictionary where decode like '" 
    					+ parentCode + "%' and length(decode) = ? order by decode", new Object[]{parentCode.length() + 3});
    		if(dictionaries == null){
    			return null;
    		}
    		JSONArray jarr = JSONArray.fromObject(dictionaries, jsonConfig);
    		jObj.put("sub", jarr);
    		CacheUtils.setCacheValue(CACHE_NAME, CACHE_DICTIONARY_KEY_PREFIX + parentCode, jObj);
    		return jarr;
    	}
    	return (JSONArray) obj;
    }
}
